import gtk

class WidgetNode:
    _widgets = {
        "chrono":    [],
        "IDs":       {}
    }

    def __init__(self, widget, parent = None):
        self.widget = widget
        self.parent = parent
        self.children = self.getChildren()
        self.ID = self.__setID()
        try:
            self.parent.setAttr(self.getType(), self)
        except:
            pass

    def getChildren(self):
        try:
            return [WidgetNode(child, self) for child in self.widget.get_children()]
        except:
            return []

    def setAttr(self, name, value):
        if name in dir(self):
            if type(getattr(self, name)) is list:
                getattr(self, name).append(value)
            else:
                older = getattr(self, name)
                setattr(self, name, [older,])
                getattr(self, name).append(value)
        else:
            setattr(self, name, value)
    
    def __call__(self):
        return self.widget

    def getType(self):
        return self.widget.get_name().lower().replace("gtk","")

    def getElementsByType(self, givenType, result = []):
        for child in self.children:
            if child.getType() == givenType:
                result.append(child)
            if child.children:
                child.getElementsByType(givenType, result)
        return result

    def getPrevSibling(self):
        try:
            index = self.parent.children.index(self)
            if index != 0:
                return self.parent.children[index-1]
            else:    raise
        except:
            return None

    def getNextSibling(self):
        try:
            index = self.parent.children.index(self)
            if index != len(self.parent.children)-1:
                return self.parent.children[index+1]
            else:    raise
        except:
            return None

    def __setID(self):
        name = self.widget.get_name()
        ID = (name in WidgetNode._widgets["chrono"]
            and "%s%s" % (name, WidgetNode._widgets["chrono"].count(name))
            or "%s%s" % (name, 1)
        )
        WidgetNode._widgets["chrono"].append(name)
        WidgetNode._widgets["IDs"].__setitem__(ID, self)
        return ID

    def changeID(self, ID):
        if ID not in WidgetNode._widgets["IDs"]:
            WidgetNode._widgets["IDs"].__setitem__(ID, self)
            self.ID = ID
            return True
        else:
            return False

    def getElementByID(self, givenID):
        try:
            return WidgetNode._widgets["IDs"][givenID]
        except:
            return None

    """def getTree(self, level = 0, output = ""):
        if level == 0: 
            output = output.__add__("]-%s\n" % self.getType())
        for child in self.children:
            output = output.__add__((
                child.getNextSibling()
                and "%s|-%s\n" % ("  "*(level+1), child.getType())
                or (
                    child.parent.getNextSibling()
                    and "%s%s`-%s\n" % ("  "*level, "| ", child.getType())
                    or "%s`-%s\n" % ("  "*(level+1), child.getType())
                )
            ))
            if child.children:
                output = child.getTree(level+1, output)
        return output"""
        
    def getTree(self, lv=[0]): # <--- 100% Wolf's code :P
        s = not lv[:-1] and ']-' or ''
        for x in lv[:-1]:
            s += x and '| ' or '  '
        if len(lv[:-1]):
            s += lv[-1] and '|-' or '`-'
        print s+self.getType()
        l=len(self.children)
        for child in self.children:
            l -= 1; child.getTree(lv+[l])
        return s

    def addChild(self, widget):
        self.childrens.append(WidgetNode(widget, self))

class testSuite:
    
    def __init__(self):
        
        self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
        self.connectEvents(self.window, {
             "delete_event" : self.delete,
             "destroy"      : self.destroy,
        })
        
        filechooser = gtk.FileChooserWidget()
        self.window.add(filechooser)
        self.window.show_all()
        
        DOM = WidgetNode(self.window)
        print DOM.getTree()
    
    def connectEvents(self, widget, events):
        for type,callback in events.items():
            widget.connect(type, callback)

    def delete(self, widget, event, data=None):
        #print "delete event occurred"
        return False

    def destroy(self, widget, data=None):
        #print "destroy signal occurred"
        gtk.main_quit()
        
    def runTest(self):
        gtk.main()
        
if __name__ == "__main__": 
    GTK = testSuite()
    GTK.runTest()